/*
 * xConsole.java
 * 
 * last update: 16.01.2010 by Stefan Saru
 * 
 * author:	Alec(panovici@elcom.pub.ro)
 * 
 * Obs:
 */

package engine;

//import java.io.*;
import middle.*;

/**
 * This is the class that handles the intaraction with the user.
 * It provides a pluggable interface to the IDE via IOManager
 */

public final class xConsole {

	static boolean __debug__ = true;
	static boolean traceEnabled = true;
	static boolean warnEnabled = true;
	static boolean tokenManagerTrace = false;

	protected static final int  COM_STEP = 0x00000010,
	COM_UNIT = 0x00000100,
	COM_GO   = 0x00001000,
	COM_EXIT = 0x00010000,
	CONSUMED = 0x00000001; //set if this command has been consumed
	protected static int command=COM_GO;

	static IOManager stdio = new DefaultIOManager();

	static Object lock;
	static {
		//    try {
		lock = new Object();
		//} catch (ClassNotFoundException cnfex) {}
	}

	public static void setIOManager(IOManager io) {
		stdio = io;
	}

	public static void setRunMode(int com) {
		command = com;
	}

	public static synchronized void display(String s) {
		stdio.cout(s);
		//lock.notifyAll();
	}

	public static synchronized void cout(String s) {
		stdio.cout(s);
		//lock.notifyAll();
	}

	public static String cin() {
		main.cronos.stop();
		String s = stdio.cin();
		main.cronos.start();
		//lock.notifyAll();
		return s;    
	}

	public static void debug(String s) {
		if (__debug__)System.out.println(s);
	}

	public static synchronized void trace(String s) {
		if (traceEnabled)stdio.cout(s + '\n');
		//lock.notifyAll();
	}

	public static synchronized void warn1(String s) {
		warn("WARNING: " + s + '\n');
		//lock.notifyAll();
	}

	public static synchronized void warn(String s) {
		if (warnEnabled) stdio.cout(s + '\n');
		//lock.notifyAll();
	}

	public static void tokenMgrTrace(String s) {
		if (tokenManagerTrace)
			System.out.println(s);
	}

	public static void enableWarnings(boolean enable) {
		warnEnabled = enable;
	}

	public static void enableTracing(boolean traceEnabled) {
		xConsole.traceEnabled = traceEnabled;
	}

	static void abort(String s) {
		debug(s);
		abort();
	}

	static void abort(String s, Exception ex) {
		debug(s);
		cout("at:");
		ex.printStackTrace();
		abort();
	}

	static void abort() {
		debug("stack dump in abort():");
		Thread.dumpStack();
		throw new Error("aborting program");
	}

	static void dumpStack(Throwable th) {
		if (__debug__)th.printStackTrace();
	}

	public static void getCommand() {
		String s;
		while(true) {
			cout("> ");
			s = cin();
			if ("step".startsWith(s)) {
				command = COM_STEP;
				break;
			}
			if ("go".startsWith(s)) {
				command = COM_GO;
				break;
			}
			if ("unit".startsWith(s)) {
				command = COM_UNIT;
				break;
			}
			if ("exit".startsWith(s)) {
				command = COM_EXIT;
				cout("By !\n");
				break;
			}
			if ("traceon".startsWith(s)) {
				xConsole.cout("Tracing is: on\n");
				xConsole.enableTracing(true);
				continue;
			}
			if ("traceoff".startsWith(s)) {
				xConsole.cout("Tracing is: off\n");
				xConsole.enableTracing(false);
				continue;
			}
			if ("debug".startsWith(s)) {
				xConsole.cout("debug is: " + (__debug__ =  !__debug__) + '\n');
				continue;
			}
			if ("kill".startsWith(s)) {
				throw new Error("killing simulator");
			}
			if ("help".startsWith(s)) {
				cout("Available commands are:\n step\n go\n " +
				"unit\n exit\n traceon\n traceoff\nEnjoy !\n");
			}else
				cout("huh ? try help\n");
		}
		//lock.notifyAll();
	}

	/**
	 * THis method and getCommand() are not 'synchronized'
	 * because entering here will not alow other threads
	 * to continue their execution. When using 'em you must
	 * explicitely synchronize using the 'lock' object.
	 */
	static  boolean enableExecution() {
		if ((command & CONSUMED) != 0)getCommand();
		//lock.notifyAll();
		return (command & COM_EXIT) == 0;
	}

	synchronized static void consumeStep() {
		if ( command == COM_STEP)command |= CONSUMED;
		//lock.notifyAll();
	}

	synchronized static void consumeUnit() {
		if (command == COM_UNIT)command |= CONSUMED;
		//lock.notifyAll();
	}

}




